/*
 * =====================================================================================
 *
 *       Filename:  logger.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2008年08月27日 15时09分21秒
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  ZhixiongHong (hzx), fishwarter@gmail.com
 *        Company:  Unioncast
 *
 * =====================================================================================
 */
#include <cstdarg>
#include <iostream>
#include <fstream>
#include "exception/IOException.h"
#include "exception/ArgumentException.h"
#include "time/timer.h"
#include "logger.h"

using namespace std;

#ifdef HAS_SS_NAMESPACE
using namespace ss;
#endif
Logger::Logger(int level, string logfile):_isOpen(false)
{
	open_log_file(logfile, level);
}


bool Logger::open_log_file(string filename, int level)
{	
	if( filename.empty())
	{
		throw ArgumentException("in Logger::openLogFile(), filename is null");
		return false;	
	}
	_logfile = filename;
	_logfs.open(_logfile.c_str(), ios::app);
	if( _logfs.bad())
	{
		throw IOException("can't find " + _logfile);
		return false;
	}
	_isOpen = true;
	return true;
}

int Logger::log(int level, const char* fmt, ...)
{
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;
}

int Logger::log(int level, string& content)
{
	int ret = writelog(level, content.c_str());
	return ret;
}

int Logger::debug(string& content)
{
	int ret = writelog(LOG_DEBUG, content.c_str());
	return ret;
}

int Logger::debug(const char* fmt, ...)
{
	int level = LOG_DEBUG;
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;

}

int Logger::info(string& content)
{

	int ret = writelog(LOG_INFO, content.c_str());
	return ret;
}

int Logger::info(const char* fmt, ...)
{
	int level = LOG_INFO;
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;

}
int Logger::error(string& content)
{
	int ret = writelog(LOG_ERROR, content.c_str());
	return ret;
}

int Logger::error(const char* fmt, ...)
{
	int level = LOG_ERROR;
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;

}

int Logger::warning(string& content)
{

	int ret = writelog(LOG_WARNING, content.c_str());
	return ret;
}

int Logger::warning(const char* fmt, ...)
{
	int level = LOG_WARNING;
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;

}

int Logger::critical(string& content)
{
	
	int ret = writelog(LOG_CRITICAL, content.c_str());
	return ret;
} 

int Logger::critical(const char* fmt, ...)
{
	int level = LOG_CRITICAL;
	if(level < _level)			
	{
		return -1;
	}

    char log_buf[MAX_LOG_LEN];
    int ret = 0 ; 
       
    va_list arg_list;
    va_start(arg_list,fmt);
    ret = vsnprintf(log_buf,sizeof(log_buf)-1,fmt,arg_list);    
    if (ret < 0){ 
        cerr << "could not format the log string..." << endl;
        return ret;
    }   
    va_end(arg_list);

	ret = writelog(level, log_buf);
	return ret;

}

int Logger::writelog(int level, const char* content)
{
	string timeStr;
	Timer::cur_time(timeStr);
	
	string levelInfo = get_level_info(level);
	
	if( _isOpen)	 // append to file
	{	
		_logfs << timeStr << "\t" << levelInfo << "\t" << content << endl;
		_logfs.flush();
	}
	else // append to print 
	{
		cout << timeStr << "\t" << levelInfo << "\t" << content << endl;
	}
	return 0;
}

string Logger::get_level_info(int level)
{
	string info = " ";
	switch(level)
	{
		case LOG_DEBUG:
		{
			info = " DEBUG ";
			break;
		}		
		case LOG_INFO:
		{
			info = " INFO ";
			break;
		}
		case LOG_WARNING:
		{
			info = " WARNING ";
			break;
		}
		case LOG_ERROR:
		{
			info = " ERROR ";
			break;
		}
		case LOG_CRITICAL:
		{
			info = " CRITICAL ";
			break;
		}
		default:
			break;
	}
	return info;
}
/*
int main()
{
	Logger* g_logger = new Logger();
	g_logger->log(Logger::DEBUG, "dd");

	return 1;
}
*/
